from django.contrib import admin
from django.contrib.admin import ModelAdmin
from django.http import HttpResponse
from django.utils import timezone
from openpyxl import Workbook

from chatbot.const import const


class ReadOnlyModelAdmin(admin.ModelAdmin):
    """ModelAdmin class that prevents modifications through the admin.

    The changelist and the detail view work, but a 403 is returned
    if one actually tries to edit an object.
    """

    actions = None

    def get_readonly_fields(self, request, obj=None):
        return self.fields or [f.name for f in self.model._meta.fields]

    def has_add_permission(self, request):
        return False

    # Allow viewing objects but not actually changing them
    def has_change_permission(self, request, obj=None):
        if request.method not in ('GET', 'HEAD'):
            return False
        return super(ReadOnlyModelAdmin, self).has_change_permission(request, obj)

    def has_delete_permission(self, request, obj=None):
        return False


class MultiTenantAdmin(ModelAdmin):
    def get_queryset(self, request):
        user = request.user
        if user.tenant:
            tenant_id = user.tenant.id
        else:
            tenant_id = const.SUPER_TENANT_ID

        qs = super(ModelAdmin, self).get_queryset(request).filter(tenant_id=tenant_id)
        return qs

    def save_model(self, request, obj, form, change):
        if not change:
            if self.has_creator(obj):
                obj.creator = request.user
            if self.has_created_at(obj):
                obj.created_at = timezone.now()
            if self.has_tenant(obj):
                obj.tenant = request.user.tenant

        if self.has_modifier(obj):
            obj.modifier = request.user
        if self.has_modified_at(obj):
            obj.modified_at = timezone.now()

        super().save_model(request, obj, form, change)

    @staticmethod
    def has_creator(obj):
        return hasattr(obj, 'creator')

    @staticmethod
    def has_created_at(obj):
        return hasattr(obj, 'created_at')

    @staticmethod
    def has_modifier(obj):
        return hasattr(obj, 'modifier')

    @staticmethod
    def has_modified_at(obj):
        return hasattr(obj, 'modified_at')

    @staticmethod
    def has_tenant(obj):
        return hasattr(obj, 'tenant')


class ExportExcelMixin(object):
    def export_as_excel(self, request, queryset):
        meta = self.model._meta
        if not self.export_fields:
            self.export_fields = [field.name for field in meta.fields]
        field_names = [field for field in self.export_fields]
        response = HttpResponse(content_type='application/msexcel')
        response['Content-Disposition'] = f'attachment; filename={meta}.xlsx'
        wb = Workbook()
        ws = wb.active
        ws.append(field_names)
        for obj in queryset:
            data = [f'{getattr(obj, field)}' for field in field_names]
            ws.append(data)
        wb.save(response)
        return response

    export_as_excel.short_description = '导出Excel'